<template>
  <Transition
    :name="transitionName"
    @afterLeave="destroyComponent"
    @enter="updateHeight"
  >
    <div
      class="v-message"
      v-show="visible"
      :class="{
        [`v-message--${type}`]: type,
        'is-close': showClose,
      }"
      role="alert"
      ref="messageRef"
      :style="cssStyle"
      @mouseenter="clearTimer"
      @mouseleave="startTimer"
    >
      <div class="v-message__content">
        <slot>
          <RenderVNode :VNode="message" v-if="message" />
        </slot>
      </div>
      <div class="v-message__close" v-if="showClose">
        <Icon icon="xmark" @click.stop="visible = false" />
      </div>
    </div>
  </Transition>
</template>

<script lang="ts" setup>
import { ref, onMounted, computed } from 'vue'
import { type MessageProps } from './types'
import RenderVNode from '../Common/RenderVNode'
import Icon from '../Icon/Icon.vue'
import { getLastBottomOffset } from './method'
import useEventListener from '../../hooks/useEventListener'

const props = withDefaults(defineProps<MessageProps>(), {
  type: 'info',
  duration: 3000,
  offset: 20,
  showClose: true,
  transitionName: 'fade-up',
})

const visible = ref(false)
// const prevInstance = getLastInstance()
const messageRef = ref<HTMLDivElement>()
// 计算偏移高度
// div 高度
const height = ref(0)
// 上一个实例底部的坐标数字,第一个是 0
const lastOffset = computed(() => getLastBottomOffset(props.id))

// 这个元素应该是用的 top
const topOffset = computed(() => props.offset + lastOffset.value)
// 这个元素为下一个元素预留的 offset, 也就是最低端的 bottom 值
const bottomOffset = computed(() => height.value + topOffset.value)

const cssStyle = computed(() => ({
  top: topOffset.value + 'px',
  'z-index': props.zIndex,
}))

const message = computed(() => {
  return props.message
})
let timer: any
function startTimer() {
  if (props.duration === 0) return
  timer = setTimeout(() => {
    visible.value = false
  }, props.duration)
}
function clearTimer() {
  clearTimeout(timer)
}

// watch(visible, (newVal) => {
//   if (!newVal) {
//     props.onDestroy()
//   }
// })
function destroyComponent() {
  props.onDestroy()
}
function updateHeight() {
  height.value = messageRef.value!.getBoundingClientRect().height
}
function keydown(e: Event) {
  const event = e as KeyboardEvent
  if (event.code === 'Escape') {
    visible.value = false
  }
}
useEventListener(document, 'keydown', keydown)
onMounted(async () => {
  visible.value = true
  startTimer()

  // await nextTick()
  // height.value = messageRef.value!.getBoundingClientRect().height
})

defineExpose({
  bottomOffset,
  visible,
})
defineOptions({ name: 'VMessage' })
</script>
<style lang="css" scoped></style>
